/*
  Copyright (c) 2023 Radxa Ltd.
  Author: Nascs <nascs@radxa.com>
          ZHANG Yuntian <yt@radxa.com>

  This Source Code Form is subject to the terms of the Mozilla Public
  License, v. 2.0. If a copy of the MPL was not distributed with this
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#include "rk3399.h"

#define GPIO_BANK_COUNT 5
#define IOMUX_COUNT 2

const static uintptr_t gpio_register_physical_address[MAX_REG_AREA] = {0xff720000, 0xff730000, 0xff780000, 0xff788000, 0xff790000};
#define GPIO_SWPORTA_DR			0x0000	// GPIO data register offset
#define GPIO_SWPORTA_DDR		0x0004	// GPIO direction control register offset
#define GPIO_EXT_PORTA			0x0050	// GPIO data read register offset

static uintptr_t pmucru_register_virtual_address = NULL;
static uintptr_t cru_register_virtual_address = NULL;
static uintptr_t pmugrf_register_virtual_address = NULL;
static uintptr_t grf_register_virtual_address = NULL;
#define PMUCRU_REGISTER_PHYSICAL_ADDRESS	0xff750000
#define CRU_REGISTER_PHYSICAL_ADDRESS			0xff760000
#define PMUGRF_REGISTER_PHYSICAL_ADDRESS	0xff320000
#define GRF_REGISTER_PHYSICAL_ADDRESS			0xff770000
#define PMUCRU_CLKGATE_CON1	0x0104	// Internal clock gating register for GPIO 0/1
#define CRU_CLKGATE_CON31		0x037c	// Internal clock gating register for GPIO 2/3/4
#define PMUGRF_GPIO0A_IOMUX	0x0000	//GPIO0A iomux control
#define PMUGRF_GPIO0B_IOMUX	0x0004	//GPIO0B iomux control
#define PMUGRF_GPIO0C_IOMUX	GRF_UNDFEIND_IOMUX	//GPIO0C is undefined on the hardware
#define PMUGRF_GPIO0D_IOMUX	GRF_UNDFEIND_IOMUX	//GPIO0D is undefined on the hardware
#define PMUGRF_GPIO1A_IOMUX	0x0010	//GPIO1A iomux control
#define PMUGRF_GPIO1B_IOMUX	0x0014	//GPIO1B iomux control
#define PMUGRF_GPIO1C_IOMUX	0x0018	//GPIO1C iomux control
#define PMUGRF_GPIO1D_IOMUX	0x001C	//GPIO1D iomux control
#define GRF_GPIO2A_IOMUX		0xe000	//GPIO2A iomux control
#define GRF_GPIO2B_IOMUX		0xe004	//GPIO2B iomux control
#define GRF_GPIO2C_IOMUX		0xe008	//GPIO2C iomux control
#define GRF_GPIO2D_IOMUX		0xe00c	//GPIO2D iomux control
#define GRF_GPIO3A_IOMUX		0xe010	//GPIO3A iomux control
#define GRF_GPIO3B_IOMUX		0xe014	//GPIO3B iomux control
#define GRF_GPIO3C_IOMUX		0xe018	//GPIO3C iomux control
#define GRF_GPIO3D_IOMUX		0xe01c	//GPIO3D iomux control
#define GRF_GPIO4A_IOMUX		0xe020	//GPIO4A iomux control
#define GRF_GPIO4B_IOMUX		0xe024	//GPIO4B iomux control
#define GRF_GPIO4C_IOMUX		0xe028	//GPIO4C iomux control
#define GRF_GPIO4D_IOMUX		0xe02c	//GPIO4D iomux control

struct soc_t *rk3399 = NULL;

static struct layout_t layout[] = {
	{"GPIO0_A0", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0A_IOMUX, 0}, {GPIO_SWPORTA_DDR, 0}, {GPIO_SWPORTA_DR, 0}, {GPIO_EXT_PORTA, 0}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_A1", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0A_IOMUX, 2}, {GPIO_SWPORTA_DDR, 1}, {GPIO_SWPORTA_DR, 1}, {GPIO_EXT_PORTA, 1}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_A2", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0A_IOMUX, 4}, {GPIO_SWPORTA_DDR, 2}, {GPIO_SWPORTA_DR, 2}, {GPIO_EXT_PORTA, 2}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_A3", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0A_IOMUX, 6}, {GPIO_SWPORTA_DDR, 3}, {GPIO_SWPORTA_DR, 3}, {GPIO_EXT_PORTA, 3}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_A4", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0A_IOMUX, 8}, {GPIO_SWPORTA_DDR, 4}, {GPIO_SWPORTA_DR, 4}, {GPIO_EXT_PORTA, 4}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_A5", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0A_IOMUX, 10}, {GPIO_SWPORTA_DDR, 5}, {GPIO_SWPORTA_DR, 4}, {GPIO_EXT_PORTA, 5}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_A6", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0A_IOMUX, 12}, {GPIO_SWPORTA_DDR, 6}, {GPIO_SWPORTA_DR, 6}, {GPIO_EXT_PORTA, 6}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_A7", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0A_IOMUX, 14}, {GPIO_SWPORTA_DDR, 7}, {GPIO_SWPORTA_DR, 7}, {GPIO_EXT_PORTA, 7}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_B0", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0B_IOMUX, 0}, {GPIO_SWPORTA_DDR, 8}, {GPIO_SWPORTA_DR, 8}, {GPIO_EXT_PORTA, 8}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_B1", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0B_IOMUX, 2}, {GPIO_SWPORTA_DDR, 9}, {GPIO_SWPORTA_DR, 9}, {GPIO_EXT_PORTA, 9}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_B2", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0B_IOMUX, 4}, {GPIO_SWPORTA_DDR, 10}, {GPIO_SWPORTA_DR, 10}, {GPIO_EXT_PORTA, 10}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_B3", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0B_IOMUX, 6}, {GPIO_SWPORTA_DDR, 11}, {GPIO_SWPORTA_DR, 11}, {GPIO_EXT_PORTA, 11}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_B4", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0B_IOMUX, 8}, {GPIO_SWPORTA_DDR, 12}, {GPIO_SWPORTA_DR, 12}, {GPIO_EXT_PORTA, 12}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_B5", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0B_IOMUX, 10}, {GPIO_SWPORTA_DDR, 13}, {GPIO_SWPORTA_DR, 13}, {GPIO_EXT_PORTA, 13}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_B6", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0B_IOMUX, 12}, {GPIO_SWPORTA_DDR, 14}, {GPIO_SWPORTA_DR, 14}, {GPIO_EXT_PORTA, 14}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_B7", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0B_IOMUX, 14}, {GPIO_SWPORTA_DDR, 15}, {GPIO_SWPORTA_DR, 15}, {GPIO_EXT_PORTA, 15}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_C0", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0C_IOMUX, 0}, {GPIO_SWPORTA_DDR, 16}, {GPIO_SWPORTA_DR, 16}, {GPIO_EXT_PORTA, 16}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_C1", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0C_IOMUX, 2}, {GPIO_SWPORTA_DDR, 17}, {GPIO_SWPORTA_DR, 17}, {GPIO_EXT_PORTA, 17}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_C2", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0C_IOMUX, 4}, {GPIO_SWPORTA_DDR, 18}, {GPIO_SWPORTA_DR, 18}, {GPIO_EXT_PORTA, 18}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_C3", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0C_IOMUX, 6}, {GPIO_SWPORTA_DDR, 19}, {GPIO_SWPORTA_DR, 19}, {GPIO_EXT_PORTA, 19}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_C4", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0C_IOMUX, 8}, {GPIO_SWPORTA_DDR, 20}, {GPIO_SWPORTA_DR, 20}, {GPIO_EXT_PORTA, 20}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_C5", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0C_IOMUX, 10}, {GPIO_SWPORTA_DDR, 21}, {GPIO_SWPORTA_DR, 21}, {GPIO_EXT_PORTA, 21}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_C6", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0C_IOMUX, 12}, {GPIO_SWPORTA_DDR, 22}, {GPIO_SWPORTA_DR, 22}, {GPIO_EXT_PORTA, 22}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_C7", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0C_IOMUX, 14}, {GPIO_SWPORTA_DDR, 23}, {GPIO_SWPORTA_DR, 23}, {GPIO_EXT_PORTA, 23}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_D0", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0D_IOMUX, 0}, {GPIO_SWPORTA_DDR, 24}, {GPIO_SWPORTA_DR, 24}, {GPIO_EXT_PORTA, 24}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_D1", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0D_IOMUX, 2}, {GPIO_SWPORTA_DDR, 25}, {GPIO_SWPORTA_DR, 25}, {GPIO_EXT_PORTA, 25}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_D2", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0D_IOMUX, 4}, {GPIO_SWPORTA_DDR, 26}, {GPIO_SWPORTA_DR, 26}, {GPIO_EXT_PORTA, 26}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_D3", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0D_IOMUX, 6}, {GPIO_SWPORTA_DDR, 27}, {GPIO_SWPORTA_DR, 27}, {GPIO_EXT_PORTA, 27}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_D4", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0D_IOMUX, 8}, {GPIO_SWPORTA_DDR, 28}, {GPIO_SWPORTA_DR, 28}, {GPIO_EXT_PORTA, 28}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_D5", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0D_IOMUX, 10}, {GPIO_SWPORTA_DDR, 29}, {GPIO_SWPORTA_DR, 29}, {GPIO_EXT_PORTA, 29}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_D6", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0D_IOMUX, 12}, {GPIO_SWPORTA_DDR, 30}, {GPIO_SWPORTA_DR, 30}, {GPIO_EXT_PORTA, 30}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO0_D7", 0, 0, {PMUCRU_CLKGATE_CON1, 3}, {PMUGRF_GPIO0D_IOMUX, 14}, {GPIO_SWPORTA_DDR, 31}, {GPIO_SWPORTA_DR, 31}, {GPIO_EXT_PORTA, 31}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_A0", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1A_IOMUX, 0}, {GPIO_SWPORTA_DDR, 0}, {GPIO_SWPORTA_DR, 0}, {GPIO_EXT_PORTA, 0}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_A1", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1A_IOMUX, 2}, {GPIO_SWPORTA_DDR, 1}, {GPIO_SWPORTA_DR, 1}, {GPIO_EXT_PORTA, 1}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_A2", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1A_IOMUX, 4}, {GPIO_SWPORTA_DDR, 2}, {GPIO_SWPORTA_DR, 2}, {GPIO_EXT_PORTA, 2}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_A3", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1A_IOMUX, 6}, {GPIO_SWPORTA_DDR, 3}, {GPIO_SWPORTA_DR, 3}, {GPIO_EXT_PORTA, 3}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_A4", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1A_IOMUX, 8}, {GPIO_SWPORTA_DDR, 4}, {GPIO_SWPORTA_DR, 4}, {GPIO_EXT_PORTA, 4}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_A5", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1A_IOMUX, 10}, {GPIO_SWPORTA_DDR, 5}, {GPIO_SWPORTA_DR, 5}, {GPIO_EXT_PORTA, 5}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_A6", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1A_IOMUX, 12}, {GPIO_SWPORTA_DDR, 6}, {GPIO_SWPORTA_DR, 6}, {GPIO_EXT_PORTA, 6}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_A7", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1A_IOMUX, 14}, {GPIO_SWPORTA_DDR, 7}, {GPIO_SWPORTA_DR, 7}, {GPIO_EXT_PORTA, 7}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_B0", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1B_IOMUX, 0}, {GPIO_SWPORTA_DDR, 8}, {GPIO_SWPORTA_DR, 8}, {GPIO_EXT_PORTA, 8}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_B1", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1B_IOMUX, 2}, {GPIO_SWPORTA_DDR, 9}, {GPIO_SWPORTA_DR, 9}, {GPIO_EXT_PORTA, 9}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_B2", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1B_IOMUX, 4}, {GPIO_SWPORTA_DDR, 10}, {GPIO_SWPORTA_DR, 10}, {GPIO_EXT_PORTA, 10}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_B3", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1B_IOMUX, 6}, {GPIO_SWPORTA_DDR, 11}, {GPIO_SWPORTA_DR, 11}, {GPIO_EXT_PORTA, 11}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_B4", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1B_IOMUX, 8}, {GPIO_SWPORTA_DDR, 12}, {GPIO_SWPORTA_DR, 12}, {GPIO_EXT_PORTA, 12}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_B5", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1B_IOMUX, 10}, {GPIO_SWPORTA_DDR, 13}, {GPIO_SWPORTA_DR, 13}, {GPIO_EXT_PORTA, 13}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_B6", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1B_IOMUX, 12}, {GPIO_SWPORTA_DDR, 14}, {GPIO_SWPORTA_DR, 14}, {GPIO_EXT_PORTA, 14}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_B7", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1B_IOMUX, 14}, {GPIO_SWPORTA_DDR, 15}, {GPIO_SWPORTA_DR, 15}, {GPIO_EXT_PORTA, 15}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_C0", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1C_IOMUX, 0}, {GPIO_SWPORTA_DDR, 16}, {GPIO_SWPORTA_DR, 16}, {GPIO_EXT_PORTA, 16}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_C1", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1C_IOMUX, 2}, {GPIO_SWPORTA_DDR, 17}, {GPIO_SWPORTA_DR, 17}, {GPIO_EXT_PORTA, 17}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_C2", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1C_IOMUX, 4}, {GPIO_SWPORTA_DDR, 18}, {GPIO_SWPORTA_DR, 18}, {GPIO_EXT_PORTA, 18}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_C3", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1C_IOMUX, 6}, {GPIO_SWPORTA_DDR, 19}, {GPIO_SWPORTA_DR, 19}, {GPIO_EXT_PORTA, 19}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_C4", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1C_IOMUX, 8}, {GPIO_SWPORTA_DDR, 20}, {GPIO_SWPORTA_DR, 20}, {GPIO_EXT_PORTA, 20}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_C5", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1C_IOMUX, 10}, {GPIO_SWPORTA_DDR, 21}, {GPIO_SWPORTA_DR, 21}, {GPIO_EXT_PORTA, 21}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_C6", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1C_IOMUX, 12}, {GPIO_SWPORTA_DDR, 22}, {GPIO_SWPORTA_DR, 22}, {GPIO_EXT_PORTA, 22}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_C7", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1C_IOMUX, 14}, {GPIO_SWPORTA_DDR, 23}, {GPIO_SWPORTA_DR, 23}, {GPIO_EXT_PORTA, 23}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_D0", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1D_IOMUX, 0}, {GPIO_SWPORTA_DDR, 24}, {GPIO_SWPORTA_DR, 24}, {GPIO_EXT_PORTA, 24}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_D1", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1D_IOMUX, 2}, {GPIO_SWPORTA_DDR, 25}, {GPIO_SWPORTA_DR, 25}, {GPIO_EXT_PORTA, 25}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_D2", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1D_IOMUX, 4}, {GPIO_SWPORTA_DDR, 26}, {GPIO_SWPORTA_DR, 26}, {GPIO_EXT_PORTA, 26}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_D3", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1D_IOMUX, 6}, {GPIO_SWPORTA_DDR, 27}, {GPIO_SWPORTA_DR, 27}, {GPIO_EXT_PORTA, 27}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_D4", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1D_IOMUX, 8}, {GPIO_SWPORTA_DDR, 28}, {GPIO_SWPORTA_DR, 28}, {GPIO_EXT_PORTA, 28}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_D5", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1D_IOMUX, 10}, {GPIO_SWPORTA_DDR, 29}, {GPIO_SWPORTA_DR, 29}, {GPIO_EXT_PORTA, 29}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_D6", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1D_IOMUX, 12}, {GPIO_SWPORTA_DDR, 30}, {GPIO_SWPORTA_DR, 30}, {GPIO_EXT_PORTA, 30}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO1_D7", 1, 0, {PMUCRU_CLKGATE_CON1, 4}, {PMUGRF_GPIO1D_IOMUX, 14}, {GPIO_SWPORTA_DDR, 31}, {GPIO_SWPORTA_DR, 31}, {GPIO_EXT_PORTA, 31}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_A0", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2A_IOMUX, 0}, {GPIO_SWPORTA_DDR, 0}, {GPIO_SWPORTA_DR, 0}, {GPIO_EXT_PORTA, 0}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_A1", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2A_IOMUX, 2}, {GPIO_SWPORTA_DDR, 1}, {GPIO_SWPORTA_DR, 1}, {GPIO_EXT_PORTA, 1}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_A2", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2A_IOMUX, 4}, {GPIO_SWPORTA_DDR, 2}, {GPIO_SWPORTA_DR, 2}, {GPIO_EXT_PORTA, 2}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_A3", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2A_IOMUX, 6}, {GPIO_SWPORTA_DDR, 3}, {GPIO_SWPORTA_DR, 3}, {GPIO_EXT_PORTA, 3}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_A4", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2A_IOMUX, 8}, {GPIO_SWPORTA_DDR, 4}, {GPIO_SWPORTA_DR, 4}, {GPIO_EXT_PORTA, 4}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_A5", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2A_IOMUX, 10}, {GPIO_SWPORTA_DDR, 5}, {GPIO_SWPORTA_DR, 5}, {GPIO_EXT_PORTA, 5}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_A6", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2A_IOMUX, 12}, {GPIO_SWPORTA_DDR, 6}, {GPIO_SWPORTA_DR, 6}, {GPIO_EXT_PORTA, 6}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_A7", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2A_IOMUX, 14}, {GPIO_SWPORTA_DDR, 7}, {GPIO_SWPORTA_DR, 7}, {GPIO_EXT_PORTA, 7}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_B0", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2B_IOMUX, 0}, {GPIO_SWPORTA_DDR, 8}, {GPIO_SWPORTA_DR, 8}, {GPIO_EXT_PORTA, 8}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_B1", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2B_IOMUX, 2}, {GPIO_SWPORTA_DDR, 9}, {GPIO_SWPORTA_DR, 9}, {GPIO_EXT_PORTA, 9}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_B2", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2B_IOMUX, 4}, {GPIO_SWPORTA_DDR, 10}, {GPIO_SWPORTA_DR, 10}, {GPIO_EXT_PORTA, 10}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_B3", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2B_IOMUX, 6}, {GPIO_SWPORTA_DDR, 11}, {GPIO_SWPORTA_DR, 11}, {GPIO_EXT_PORTA, 11}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_B4", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2B_IOMUX, 8}, {GPIO_SWPORTA_DDR, 12}, {GPIO_SWPORTA_DR, 12}, {GPIO_EXT_PORTA, 12}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_B5", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2B_IOMUX, 10}, {GPIO_SWPORTA_DDR, 13}, {GPIO_SWPORTA_DR, 13}, {GPIO_EXT_PORTA, 13}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_B6", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2B_IOMUX, 12}, {GPIO_SWPORTA_DDR, 14}, {GPIO_SWPORTA_DR, 14}, {GPIO_EXT_PORTA, 14}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_B7", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2B_IOMUX, 14}, {GPIO_SWPORTA_DDR, 15}, {GPIO_SWPORTA_DR, 15}, {GPIO_EXT_PORTA, 15}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_C0", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2C_IOMUX, 0}, {GPIO_SWPORTA_DDR, 16}, {GPIO_SWPORTA_DR, 16}, {GPIO_EXT_PORTA, 16}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_C1", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2C_IOMUX, 2}, {GPIO_SWPORTA_DDR, 17}, {GPIO_SWPORTA_DR, 17}, {GPIO_EXT_PORTA, 17}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_C2", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2C_IOMUX, 4}, {GPIO_SWPORTA_DDR, 18}, {GPIO_SWPORTA_DR, 18}, {GPIO_EXT_PORTA, 18}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_C3", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2C_IOMUX, 6}, {GPIO_SWPORTA_DDR, 19}, {GPIO_SWPORTA_DR, 19}, {GPIO_EXT_PORTA, 19}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_C4", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2C_IOMUX, 8}, {GPIO_SWPORTA_DDR, 20}, {GPIO_SWPORTA_DR, 20}, {GPIO_EXT_PORTA, 20}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_C5", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2C_IOMUX, 10}, {GPIO_SWPORTA_DDR, 21}, {GPIO_SWPORTA_DR, 21}, {GPIO_EXT_PORTA, 21}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_C6", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2C_IOMUX, 12}, {GPIO_SWPORTA_DDR, 22}, {GPIO_SWPORTA_DR, 22}, {GPIO_EXT_PORTA, 22}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_C7", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2C_IOMUX, 14}, {GPIO_SWPORTA_DDR, 23}, {GPIO_SWPORTA_DR, 23}, {GPIO_EXT_PORTA, 23}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_D0", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2D_IOMUX, 0}, {GPIO_SWPORTA_DDR, 24}, {GPIO_SWPORTA_DR, 24}, {GPIO_EXT_PORTA, 24}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_D1", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2D_IOMUX, 2}, {GPIO_SWPORTA_DDR, 25}, {GPIO_SWPORTA_DR, 25}, {GPIO_EXT_PORTA, 25}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_D2", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2D_IOMUX, 4}, {GPIO_SWPORTA_DDR, 26}, {GPIO_SWPORTA_DR, 26}, {GPIO_EXT_PORTA, 26}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_D3", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2D_IOMUX, 6}, {GPIO_SWPORTA_DDR, 27}, {GPIO_SWPORTA_DR, 27}, {GPIO_EXT_PORTA, 27}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_D4", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2D_IOMUX, 10}, {GPIO_SWPORTA_DDR, 28}, {GPIO_SWPORTA_DR, 28}, {GPIO_EXT_PORTA, 28}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_D5", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2D_IOMUX, 12}, {GPIO_SWPORTA_DDR, 29}, {GPIO_SWPORTA_DR, 29}, {GPIO_EXT_PORTA, 29}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_D6", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2D_IOMUX, 14}, {GPIO_SWPORTA_DDR, 30}, {GPIO_SWPORTA_DR, 30}, {GPIO_EXT_PORTA, 30}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO2_D7", 2, 1, {CRU_CLKGATE_CON31, 3}, {GRF_GPIO2D_IOMUX, 16}, {GPIO_SWPORTA_DDR, 31}, {GPIO_SWPORTA_DR, 31}, {GPIO_EXT_PORTA, 31}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_A0", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3A_IOMUX, 0}, {GPIO_SWPORTA_DDR, 0}, {GPIO_SWPORTA_DR, 0}, {GPIO_EXT_PORTA, 0}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_A1", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3A_IOMUX, 2}, {GPIO_SWPORTA_DDR, 1}, {GPIO_SWPORTA_DR, 1}, {GPIO_EXT_PORTA, 1}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_A2", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3A_IOMUX, 4}, {GPIO_SWPORTA_DDR, 2}, {GPIO_SWPORTA_DR, 2}, {GPIO_EXT_PORTA, 2}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_A3", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3A_IOMUX, 6}, {GPIO_SWPORTA_DDR, 3}, {GPIO_SWPORTA_DR, 3}, {GPIO_EXT_PORTA, 3}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_A4", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3A_IOMUX, 8}, {GPIO_SWPORTA_DDR, 4}, {GPIO_SWPORTA_DR, 4}, {GPIO_EXT_PORTA, 4}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_A5", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3A_IOMUX, 10}, {GPIO_SWPORTA_DDR, 5}, {GPIO_SWPORTA_DR, 5}, {GPIO_EXT_PORTA, 5}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_A6", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3A_IOMUX, 12}, {GPIO_SWPORTA_DDR, 6}, {GPIO_SWPORTA_DR, 6}, {GPIO_EXT_PORTA, 6}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_A7", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3A_IOMUX, 14}, {GPIO_SWPORTA_DDR, 7}, {GPIO_SWPORTA_DR, 7}, {GPIO_EXT_PORTA, 7}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_B0", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3B_IOMUX, 0}, {GPIO_SWPORTA_DDR, 8}, {GPIO_SWPORTA_DR, 8}, {GPIO_EXT_PORTA, 8}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_B1", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3B_IOMUX, 2}, {GPIO_SWPORTA_DDR, 9}, {GPIO_SWPORTA_DR, 9}, {GPIO_EXT_PORTA, 9}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_B2", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3B_IOMUX, 4}, {GPIO_SWPORTA_DDR, 10}, {GPIO_SWPORTA_DR, 10}, {GPIO_EXT_PORTA, 10}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_B3", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3B_IOMUX, 6}, {GPIO_SWPORTA_DDR, 11}, {GPIO_SWPORTA_DR, 11}, {GPIO_EXT_PORTA, 11}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_B4", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3B_IOMUX, 8}, {GPIO_SWPORTA_DDR, 12}, {GPIO_SWPORTA_DR, 12}, {GPIO_EXT_PORTA, 12}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_B5", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3B_IOMUX, 10}, {GPIO_SWPORTA_DDR, 13}, {GPIO_SWPORTA_DR, 13}, {GPIO_EXT_PORTA, 13}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_B6", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3B_IOMUX, 12}, {GPIO_SWPORTA_DDR, 14}, {GPIO_SWPORTA_DR, 14}, {GPIO_EXT_PORTA, 14}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_B7", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3B_IOMUX, 14}, {GPIO_SWPORTA_DDR, 15}, {GPIO_SWPORTA_DR, 15}, {GPIO_EXT_PORTA, 15}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_C0", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3C_IOMUX, 0}, {GPIO_SWPORTA_DDR, 16}, {GPIO_SWPORTA_DR, 16}, {GPIO_EXT_PORTA, 16}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_C1", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3C_IOMUX, 2}, {GPIO_SWPORTA_DDR, 17}, {GPIO_SWPORTA_DR, 17}, {GPIO_EXT_PORTA, 17}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_C2", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3C_IOMUX, 4}, {GPIO_SWPORTA_DDR, 18}, {GPIO_SWPORTA_DR, 18}, {GPIO_EXT_PORTA, 18}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_C3", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3C_IOMUX, 6}, {GPIO_SWPORTA_DDR, 19}, {GPIO_SWPORTA_DR, 19}, {GPIO_EXT_PORTA, 19}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_C4", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3C_IOMUX, 8}, {GPIO_SWPORTA_DDR, 20}, {GPIO_SWPORTA_DR, 20}, {GPIO_EXT_PORTA, 20}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_C5", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3C_IOMUX, 10}, {GPIO_SWPORTA_DDR, 21}, {GPIO_SWPORTA_DR, 21}, {GPIO_EXT_PORTA, 21}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_C6", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3C_IOMUX, 12}, {GPIO_SWPORTA_DDR, 22}, {GPIO_SWPORTA_DR, 22}, {GPIO_EXT_PORTA, 22}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_C7", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3C_IOMUX, 14}, {GPIO_SWPORTA_DDR, 23}, {GPIO_SWPORTA_DR, 23}, {GPIO_EXT_PORTA, 23}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_D0", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3D_IOMUX, 0}, {GPIO_SWPORTA_DDR, 24}, {GPIO_SWPORTA_DR, 24}, {GPIO_EXT_PORTA, 24}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_D1", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3D_IOMUX, 2}, {GPIO_SWPORTA_DDR, 25}, {GPIO_SWPORTA_DR, 25}, {GPIO_EXT_PORTA, 25}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_D2", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3D_IOMUX, 4}, {GPIO_SWPORTA_DDR, 26}, {GPIO_SWPORTA_DR, 26}, {GPIO_EXT_PORTA, 26}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_D3", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3D_IOMUX, 6}, {GPIO_SWPORTA_DDR, 27}, {GPIO_SWPORTA_DR, 27}, {GPIO_EXT_PORTA, 27}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_D4", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3D_IOMUX, 8}, {GPIO_SWPORTA_DDR, 28}, {GPIO_SWPORTA_DR, 28}, {GPIO_EXT_PORTA, 28}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_D5", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3D_IOMUX, 10}, {GPIO_SWPORTA_DDR, 29}, {GPIO_SWPORTA_DR, 29}, {GPIO_EXT_PORTA, 29}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_D6", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3D_IOMUX, 12}, {GPIO_SWPORTA_DDR, 30}, {GPIO_SWPORTA_DR, 30}, {GPIO_EXT_PORTA, 30}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO3_D7", 3, 1, {CRU_CLKGATE_CON31, 4}, {GRF_GPIO3D_IOMUX, 14}, {GPIO_SWPORTA_DDR, 31}, {GPIO_SWPORTA_DR, 31}, {GPIO_EXT_PORTA, 31}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_A0", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4A_IOMUX, 0}, {GPIO_SWPORTA_DDR, 0}, {GPIO_SWPORTA_DR, 0}, {GPIO_EXT_PORTA, 0}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_A1", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4A_IOMUX, 2}, {GPIO_SWPORTA_DDR, 1}, {GPIO_SWPORTA_DR, 1}, {GPIO_EXT_PORTA, 1}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_A2", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4A_IOMUX, 4}, {GPIO_SWPORTA_DDR, 2}, {GPIO_SWPORTA_DR, 2}, {GPIO_EXT_PORTA, 2}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_A3", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4A_IOMUX, 6}, {GPIO_SWPORTA_DDR, 3}, {GPIO_SWPORTA_DR, 3}, {GPIO_EXT_PORTA, 3}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_A4", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4A_IOMUX, 8}, {GPIO_SWPORTA_DDR, 4}, {GPIO_SWPORTA_DR, 4}, {GPIO_EXT_PORTA, 4}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_A5", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4A_IOMUX, 10}, {GPIO_SWPORTA_DDR, 5}, {GPIO_SWPORTA_DR, 5}, {GPIO_EXT_PORTA, 5}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_A6", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4A_IOMUX, 12}, {GPIO_SWPORTA_DDR, 6}, {GPIO_SWPORTA_DR, 6}, {GPIO_EXT_PORTA, 6}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_A7", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4A_IOMUX, 14}, {GPIO_SWPORTA_DDR, 7}, {GPIO_SWPORTA_DR, 7}, {GPIO_EXT_PORTA, 7}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_B0", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4B_IOMUX, 0}, {GPIO_SWPORTA_DDR, 8}, {GPIO_SWPORTA_DR, 8}, {GPIO_EXT_PORTA, 8}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_B1", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4B_IOMUX, 2}, {GPIO_SWPORTA_DDR, 9}, {GPIO_SWPORTA_DR, 9}, {GPIO_EXT_PORTA, 9}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_B2", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4B_IOMUX, 4}, {GPIO_SWPORTA_DDR, 10}, {GPIO_SWPORTA_DR, 10}, {GPIO_EXT_PORTA, 10}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_B3", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4B_IOMUX, 6}, {GPIO_SWPORTA_DDR, 11}, {GPIO_SWPORTA_DR, 11}, {GPIO_EXT_PORTA, 11}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_B4", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4B_IOMUX, 8}, {GPIO_SWPORTA_DDR, 12}, {GPIO_SWPORTA_DR, 12}, {GPIO_EXT_PORTA, 12}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_B5", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4B_IOMUX, 10}, {GPIO_SWPORTA_DDR, 13}, {GPIO_SWPORTA_DR, 13}, {GPIO_EXT_PORTA, 13}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_B6", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4B_IOMUX, 12}, {GPIO_SWPORTA_DDR, 14}, {GPIO_SWPORTA_DR, 14}, {GPIO_EXT_PORTA, 14}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_B7", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4B_IOMUX, 14}, {GPIO_SWPORTA_DDR, 15}, {GPIO_SWPORTA_DR, 15}, {GPIO_EXT_PORTA, 15}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_C0", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4C_IOMUX, 0}, {GPIO_SWPORTA_DDR, 16}, {GPIO_SWPORTA_DR, 16}, {GPIO_EXT_PORTA, 16}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_C1", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4C_IOMUX, 2}, {GPIO_SWPORTA_DDR, 17}, {GPIO_SWPORTA_DR, 17}, {GPIO_EXT_PORTA, 17}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_C2", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4C_IOMUX, 4}, {GPIO_SWPORTA_DDR, 18}, {GPIO_SWPORTA_DR, 18}, {GPIO_EXT_PORTA, 18}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_C3", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4C_IOMUX, 6}, {GPIO_SWPORTA_DDR, 19}, {GPIO_SWPORTA_DR, 19}, {GPIO_EXT_PORTA, 19}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_C4", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4C_IOMUX, 8}, {GPIO_SWPORTA_DDR, 20}, {GPIO_SWPORTA_DR, 20}, {GPIO_EXT_PORTA, 20}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_C5", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4C_IOMUX, 10}, {GPIO_SWPORTA_DDR, 21}, {GPIO_SWPORTA_DR, 21}, {GPIO_EXT_PORTA, 21}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_C6", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4C_IOMUX, 12}, {GPIO_SWPORTA_DDR, 22}, {GPIO_SWPORTA_DR, 22}, {GPIO_EXT_PORTA, 22}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_C7", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4C_IOMUX, 14}, {GPIO_SWPORTA_DDR, 23}, {GPIO_SWPORTA_DR, 23}, {GPIO_EXT_PORTA, 23}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_D0", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4D_IOMUX, 0}, {GPIO_SWPORTA_DDR, 24}, {GPIO_SWPORTA_DR, 24}, {GPIO_EXT_PORTA, 24}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_D1", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4D_IOMUX, 2}, {GPIO_SWPORTA_DDR, 25}, {GPIO_SWPORTA_DR, 25}, {GPIO_EXT_PORTA, 25}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_D2", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4D_IOMUX, 4}, {GPIO_SWPORTA_DDR, 26}, {GPIO_SWPORTA_DR, 26}, {GPIO_EXT_PORTA, 26}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_D3", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4D_IOMUX, 6}, {GPIO_SWPORTA_DDR, 27}, {GPIO_SWPORTA_DR, 27}, {GPIO_EXT_PORTA, 27}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_D4", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4D_IOMUX, 8}, {GPIO_SWPORTA_DDR, 28}, {GPIO_SWPORTA_DR, 28}, {GPIO_EXT_PORTA, 28}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_D5", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4D_IOMUX, 10}, {GPIO_SWPORTA_DDR, 29}, {GPIO_SWPORTA_DR, 29}, {GPIO_EXT_PORTA, 29}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_D6", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4D_IOMUX, 12}, {GPIO_SWPORTA_DDR, 30}, {GPIO_SWPORTA_DR, 30}, {GPIO_EXT_PORTA, 30}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
	{"GPIO4_D7", 4, 1, {CRU_CLKGATE_CON31, 5}, {GRF_GPIO4D_IOMUX, 14}, {GPIO_SWPORTA_DDR, 31}, {GPIO_SWPORTA_DR, 31}, {GPIO_EXT_PORTA, 31}, FUNCTION_DIGITAL, PINMODE_NOT_SET, 0},
};

static int rk3399Setup(void) {
	int i = 0;

	if((rk3399->fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) {
		wiringXLog(LOG_ERR, "wiringX failed to open /dev/mem for raw memory access");
		return -1;
	}
	for(i = 0; i < GPIO_BANK_COUNT; i++) {
		if((rk3399->gpio[i] = (unsigned char *)rockchip_mmap(rk3399, rk3399->base_addr[i])) == NULL) {
			wiringXLog(LOG_ERR, "wiringX failed to map The %s %s GPIO memory address", rk3399->brand, rk3399->chip);
			return -1;
		}
	}
	if((cru_register_virtual_address = (unsigned char *)rockchip_mmap(rk3399, CRU_REGISTER_PHYSICAL_ADDRESS)) == NULL) {
		wiringXLog(LOG_ERR, "wiringX failed to map The %s %s CRU memory address", rk3399->brand, rk3399->chip);
		return -1;
	}
	if((pmucru_register_virtual_address = (unsigned char *)rockchip_mmap(rk3399, PMUCRU_REGISTER_PHYSICAL_ADDRESS)) == NULL) {
		wiringXLog(LOG_ERR, "wiringX failed to map The %s %s CRU memory address", rk3399->brand, rk3399->chip);
		return -1;
	}
	if((pmugrf_register_virtual_address = (unsigned char *)rockchip_mmap(rk3399, PMUGRF_REGISTER_PHYSICAL_ADDRESS)) == NULL) {
		wiringXLog(LOG_ERR, "wiringX failed to map The %s %s PMUGRF memory address", rk3399->brand, rk3399->chip);
		return -1;
	}
	if((grf_register_virtual_address = (unsigned char *)rockchip_mmap(rk3399, GRF_REGISTER_PHYSICAL_ADDRESS)) == NULL) {
		wiringXLog(LOG_ERR, "wiringX failed to map The %s %s GRF memory address", rk3399->brand, rk3399->chip);
		return -1;
	}

	return 0;
}

static char *rk3399GetPinName(int pin) {
	return rockchipGetPinName(rk3399, pin);
}

static void rk3399SetMap(int *map, size_t size) {
	rockchipSetMap(rk3399, map, size);
}

static void rk3399SetIRQ(int *irq, size_t size) {
	rockchipSetIRQ(rk3399, irq, size);
}

struct layout_t *rk3399GetLayout(int i, int *mapping) {
	return rockchipGetLayout(rk3399, i, mapping);
}

static int rk3399DigitalWrite(int i, enum digital_value_t value) {
	struct layout_t *pin = NULL;
	unsigned int *data_reg = 0;

	if((pin = rockchipGetPinLayout(rk3399, i)) == NULL) {
		return -1;
	}

	if(pin->mode != PINMODE_OUTPUT) {
		wiringXLog(LOG_ERR, "The %s %s GPIO%d is not set to output mode", rk3399->brand, rk3399->chip, i);
		return -1;
	}

	data_reg = (volatile unsigned int *)(rk3399->gpio[pin->bank] + pin->out.offset);
	if(value == HIGH) {
		*data_reg |= (1 << (pin->out.bit));
	} else if(value == LOW) {
		*data_reg &= ~(1 << (pin->out.bit));
	} else {
		wiringXLog(LOG_ERR, "invalid value %i for GPIO %i", value, i);
		return -1;
	}

	return 0;
}

static int rk3399DigitalRead(int i) {
	return rockchipDigitalRead(rk3399, i);
}

static int rk3399PinMode(int i, enum pinmode_t mode) {
	struct layout_t *pin = NULL;
	unsigned int *cru_reg = NULL;
	unsigned int *grf_reg = NULL;
	unsigned int *dir_reg = NULL;

	if((pin = rockchipGetPinLayout(rk3399, i)) == NULL) {
		return -1;
	}

	if(pin->iomux_num == 0) {
		cru_reg = (volatile unsigned int *)(pmucru_register_virtual_address + pin->cru.offset);
	} else if(pin->iomux_num == 1) {
		cru_reg = (volatile unsigned int *)(cru_register_virtual_address + pin->cru.offset);
	} else {
		wiringXLog(LOG_ERR, "pin->iomux_num out of range %i, expect 0~2", i);
	}
	// set to low to enable the clock for GPIO bank
	*cru_reg = REGISTER_CLEAR_BITS(cru_reg, pin->cru.bit, 1);

	if(pin->iomux_num == 0) {
		grf_reg = (volatile unsigned int *)(pmugrf_register_virtual_address + pin->grf.offset);
	} else if(pin->iomux_num == 1) {
		grf_reg = (volatile unsigned int *)(grf_register_virtual_address + pin->grf.offset);
	} else {
		wiringXLog(LOG_ERR, "pin->iomux_num out of range %i, expect 0~2", i);
	}
	*grf_reg = REGISTER_CLEAR_BITS(grf_reg, pin->grf.bit, 2);

	dir_reg = (volatile unsigned int *)(rk3399->gpio[pin->bank] + pin->direction.offset);
	if(mode == PINMODE_INPUT) {
		*dir_reg &= ~(1 << pin->direction.bit);
	} else if(mode == PINMODE_OUTPUT) {
		*dir_reg |= (1 << pin->direction.bit);
	} else {
		wiringXLog(LOG_ERR, "invalid pin mode %i for GPIO %i", mode, i);
		return -1;
	}

	pin->mode = mode;

	return 0;
}

static int rk3399ISR(int i, enum isr_mode_t mode) {
	return rockchipISR(rk3399, i, mode);
}

static int rk3399WaitForInterrupt(int i, int ms) {
	return rockchipWaitForInterrupt(rk3399, i, ms);
}

static int rk3399GC(void) {
	rockchipGC(rk3399);

	if(cru_register_virtual_address != NULL) {
		munmap(cru_register_virtual_address, rk3399->page_size);
		cru_register_virtual_address = NULL;
	}
	if(pmucru_register_virtual_address != NULL) {
		munmap(pmucru_register_virtual_address, rk3399->page_size);
		pmucru_register_virtual_address = NULL;
	}
	if(pmugrf_register_virtual_address != NULL) {
		munmap(pmugrf_register_virtual_address, rk3399->page_size);
		pmugrf_register_virtual_address = NULL;
	}
	if(grf_register_virtual_address != NULL) {
		munmap(grf_register_virtual_address, rk3399->page_size);
		grf_register_virtual_address = NULL;
	}
	for(int i = 0; i < GPIO_BANK_COUNT; i++) {
		if(rk3399->gpio[i] != NULL) {
			munmap(rk3399->gpio[i], rk3399->page_size);
			rk3399->gpio[i] = NULL;
		}
	}

	return 0;
}

static int rk3399SelectableFd(int i) {
	return rockchipSelectableFd(rk3399, i);
}

void rk3399Init(void) {
	soc_register(&rk3399, "Rockchip", "RK3399");

	rk3399->layout = layout;

	rk3399->support.isr_modes = ISR_MODE_RISING | ISR_MODE_FALLING | ISR_MODE_BOTH | ISR_MODE_NONE;
	rk3399->page_size = (1024*64);
	memcpy(rk3399->base_addr, gpio_register_physical_address, sizeof(gpio_register_physical_address));

	rk3399->gc = &rk3399GC;
	rk3399->selectableFd = &rk3399SelectableFd;
	rk3399->pinMode = &rk3399PinMode;
	rk3399->setup = &rk3399Setup;
	rk3399->digitalRead = &rk3399DigitalRead;
	rk3399->digitalWrite = &rk3399DigitalWrite;
	rk3399->getPinName = &rk3399GetPinName;
	rk3399->setMap = &rk3399SetMap;
	rk3399->setIRQ = &rk3399SetIRQ;
	rk3399->isr = &rk3399ISR;
	rk3399->waitForInterrupt = &rk3399WaitForInterrupt;
}
